package org.eclipse.epsilon.emc.spreadsheets.csv;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.epsilon.common.util.FileUtil;
import org.eclipse.epsilon.emc.spreadsheets.SpreadsheetColumn;
import org.eclipse.epsilon.emc.spreadsheets.SpreadsheetColumnComparator;
import org.eclipse.epsilon.emc.spreadsheets.SpreadsheetRow;
import org.eclipse.epsilon.emc.spreadsheets.SpreadsheetWorksheet;
import org.eclipse.epsilon.eol.exceptions.models.EolModelLoadingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CsvWorksheet extends SpreadsheetWorksheet
{
	private static final Logger LOGGER = LoggerFactory.getLogger(CsvWorksheet.class);

	public static final String NAME = "CSV";

	private CsvModel model;
	private File file;
	private LinkedList<CsvRow> rows = null;
	private LinkedList<String> lines = null;

	public CsvWorksheet(final CsvModel model, final File file) throws Exception
	{
		super(model, NAME, true);
		this.model = model;
		this.file = file;
		this.lines = new LinkedList<String>(FileUtil.getFileLineContents(this.file));
		this.loadHeader();
	}

	@Override
	protected void loadHeader() throws EolModelLoadingException
	{
		if (this.model.hasHeader())
		{
			LOGGER.debug("Inside loadHeader() method");
			try
			{
				final String line = this.lines.removeFirst();
				if (StringUtils.isNotBlank(line))
				{
					final CsvRow row = new CsvRow(this, line);
					for (int i = 0; i < row.getRow().size(); i++)
					{
						final String columnName = row.getRow().get(i);
						LOGGER.debug("Adding column to header; name: '" + columnName + "'");
						super.addColumn(i, columnName);
					}
				}
				else
				{
					throw new IllegalArgumentException("Header row is blank");
				}
			}
			catch (NoSuchElementException e)
			{
				throw new IllegalArgumentException("Missing header row");
			}
		}
	}

	@Override
	protected void createInSpreadsheet()
	{
		throw new UnsupportedOperationException();
	}

	@Override
	protected SpreadsheetColumn createColumn(int index)
	{
		return new CsvColumn(this, index);
	}

	@Override
	public List<SpreadsheetRow> getRows()
	{
		if (this.rows == null)
		{
			this.rows = new LinkedList<CsvRow>();
			for (final String line : this.lines)
			{
				final CsvRow row = new CsvRow(this, line);
				this.rows.add(row);
			}
		}
		return new ArrayList<SpreadsheetRow>(this.rows);
	}

	@Override
	protected SpreadsheetRow insertRow(final Map<SpreadsheetColumn, String> values)
	{
		if (this.rows == null)
		{
			this.getRows();
		}
		final CsvRow row = new CsvRow(this, "");
		row.clear();

		final SortedSet<SpreadsheetColumn> keys = new TreeSet<SpreadsheetColumn>(new SpreadsheetColumnComparator());
		keys.addAll(values.keySet());

		for (final SpreadsheetColumn column : keys)
		{
			row.addValue(values.get(column));
		}
		rows.add(row);
		return row;
	}

	@Override
	public void removeRow(SpreadsheetRow row)
	{
		this.rows.remove(row);
	}

	@Override
	public String getDefaultEmptyCellValue()

	{
		return "";
	}

}
